package com.jwdemo
{
	import com.jwdemo.Node;
	// Double linked list Class - used to handle dynamic objects - eg. Bullets,Explosions, Particle effects.
	
	
	public class LinkedList
	{
		private var _headr:Node 	;
		private var _tail:Node 		;
		private var _size:uint 		;
		
		public function LinkedList()
		{
			this._headr		=	null ;
			this._tail		=	null ;
			this._size		=	0 ;

		}
		
		/**
		 * 
		 * 
		 */		
		public function clear() : void 
		{
			this._headr	=	null ;
			this._tail	=	null ;
		}
		
		/**
		 * 
		 * @return 
		 * 
		 */		
		public function toArray() : Array 
		{
			var arr:Array = new Array() ;
			return arr ;
		}
		
		/**
		 * 
		 * @param data
		 * @return 
		 * 
		 */
		public function add(data: *) : Node 
		{
			var obj:Node 	=	new Node(data) ;
			var tail:Node	=	this._tail ;
			var headr:Node	=	this._headr;
			
			if (!tail) 
			{
				this._headr =	obj ;
				this._tail 	=	obj ;
			} else 
			{
				tail._next	=	obj ;
				obj._prev	=	this._tail ;

				this._tail	=	obj ;
			}
			this._size		=	this._size + 1 ;
			
			return obj ;

		}
		
		/**
		 * 
		 * @param arr
		 * 
		 */		
		public function addArray(arr:Array) : void
		{
			for(var idx:uint = 0 ; idx < arr.length ; idx ++)
			{
				var data:* = arr[idx] ;
				this.add(data) ;
			}	
		}
		/**
		 * 
		 * @return 
		 * 
		 */		
		public function size() : uint 
		{
			return this._size ;
		}

		/**
		 * 
		 * @param linkeddata
		 * 
		 */
		public function remove(linkeddata:Node) : void
		{
				
			var chead:Node		=	this._headr ;
			var ctail:Node		=	this._tail ;
				
			var prev:Node		=	linkeddata._prev ;
			var next:Node		=	linkeddata._next ;
				
			if (prev)
			{
				prev._next	=	next ;
			}
				
			if (next) 
			{
				next._prev	=	prev ;
			}
				
			if (chead == linkeddata)
			{
				this._headr 	=	next ;
			}
				
			if (ctail == linkeddata)
			{
				this._tail		=	prev ;
			}
				
			this._size		=	this._size - 1 ;
				
			// make sure we can't remove it again!
			linkeddata._prev			=	null ;
			linkeddata._next			=	null ;

		}
		
		/**
		 * Iterator
		 * 
		 * @param rawdata - set to true if you just want to iterate and retrieve raw data 
		 * @return returns either, rawdata (if 'rawdata' set to true) or the next Node object
		 */
		// TODO Need to make this returned some defined object from an actual class 

		public function Iterator(rawdata:Boolean = false) : Object
		{
			var raw:Boolean			=	rawdata ;
			var header:Node			=	this._headr ;
			var current:Node		=	header ;
			
			return {
				
					reset:			function():void
									{
										current = header ;
									},
				
					next:			function():Node 
									{
										if (current) 
										{
											current = current._next ;
										}
										return current ;
									},
					hasElements:	function():Node
									{
										return current ;
									},
					getCurrent:     function():*
									{
										return raw ? current.getData() : current ;
									}
				} ;
		} 

		
	}
}